package cn.ilikes.tools.hbase.jpa.indexs;

import java.util.List;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.clients.nodes.Node;
import cn.ilikes.tools.hbase.jpa.indexs.Indexer.FlushType;
import cn.ilikes.tools.hbase.jpa.indexs.lucenes.LocalLuceneIndexer;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaData;
import cn.ilikes.tools.hbase.jpa.metadatas.sub.configs.Indexfactory;
import cn.ilikes.tools.hbase.jpa.metadatas.sub.configs.Indexfactory.IndexType;
import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.untils.PropertyAccessorHelper;

public class JPAHBsaeDefultIndexClient implements IndexClient {

	private static Logger logger = Loggerfactory.instance(JPAHBsaeDefultIndexClient.class);

	private Indexer indexer;

	public JPAHBsaeDefultIndexClient(Indexfactory indexConfig) {
		init(indexConfig);
	}

	private void init(Indexfactory indexConfig) {

		IndexType indexTYpe = indexConfig.getIndexType();

		switch (indexTYpe) {
		case lucene: {
			Indexer indexerWork = new LocalLuceneIndexer(FlushType.manual, indexConfig.getProperties());
			JPAHBaseIndexer indexer = new JPAHBaseIndexer(indexerWork);
			this.setIndexer(indexer);

		}
			break;
		case hadoop: {
			throw new IndexNullException("find " + indexConfig.getType() + " index type  not work ! ");
		}

		default:
			throw new IndexNullException("not find " + indexConfig.getType() + " index type ! ");

		}

	}

	private IEntityMetaData getIEntityMetaData(Node node) {
		return node.getEntityMetaData();
	}

	@Override
	public final void remove(Node node) throws IndexManagerException {
		IEntityMetaData entityMetaData = getIEntityMetaData(node);
		if (entityMetaData.isUseSecondryIndex()) {
			if (!entityMetaData.isEntityableIndex())
				return;
			Object id = PropertyAccessorHelper.getId(node.getEntity(), entityMetaData);
			indexer.remove(node);
		}

	}

	@Override
	public void update(Node node) throws IndexManagerException {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, "start update  entity  : " + node.getEntity());
		IEntityMetaData entityMetaData = getIEntityMetaData(node);
		if (entityMetaData.isUseSecondryIndex()) {
			if (!entityMetaData.isEntityableIndex())
				return;
			if (indexer.entityExistsByEntity(node)) {
				if (Loggerfactory.isdebug(logger))
					Loggerfactory.debug(logger, "remove un index   entity  : " + node.getEntity());
				Object id = PropertyAccessorHelper.getId(node.getEntity(), entityMetaData);
				indexer.remove(node);
			}
			indexer.index(node);
		}

	}

	@Override
	public final void add(Node node) throws IndexManagerException {
		IEntityMetaData entityMetaData = getIEntityMetaData(node);
		if (entityMetaData.isUseSecondryIndex()) {
			if (!entityMetaData.isEntityableIndex()) {
				if (Loggerfactory.isdebug(logger))
					Loggerfactory.debug(logger, "this entity : " + node.getEntity() + " is   not  create index ");
				return;
			}
			if (indexer.entityExistsByEntity(node))
				indexer.update(node);
			else
				indexer.create(node);
		}
	}

	@Override
	public final <V> List<V> search(String query, IEntityMetaData metadata) throws IndexManagerException {
		return search(query, Indexer.INVALID, Indexer.INVALID, metadata, false);
	}

	@Override
	public final <V> List<V> search(String query, int start, int count, IEntityMetaData metadata) throws IndexManagerException {
		return (List<V>) indexer.search(query, start, count, metadata, false);
	}

	@Override
	public final <V> List<V> search(String query, int start, int count, IEntityMetaData metadata, boolean fetchRelation) throws IndexManagerException {
		return (List<V>) indexer.search(query, start, count, metadata, fetchRelation);
	}

	@Override
	public void flush(IEntityMetaData metadata) throws IndexManagerException {
		if (!metadata.isEntityableIndex())
			return;
		if (indexer != null) {
			indexer.flush();
		}
	}

	@Override
	public void close() throws IndexManagerException {
		if (indexer != null) {
			indexer.close();
		}
	}

	@Override
	public boolean entityExistsByEntity(Node node) throws IndexManagerException {
		IEntityMetaData entityMetaData = getIEntityMetaData(node);
		if (entityMetaData.isUseSecondryIndex()) {
			return indexer.entityExistsByEntity(node);
		} else
			throw new IndexManagerException(" entity :  " + node.getEntity() + " not use  secondry index ");

	}

	@Override
	public void commit(IEntityMetaData metadata) throws IndexManagerException {
		if (!metadata.isEntityableIndex())
			return;
		indexer.flush();

	}

	private void setIndexer(Indexer indexer) {
		this.indexer = indexer;
	}

	@Override
	public void flush() {
		indexer.flush();
	}

	@Override
	public boolean isOpen() {
		Loggerfactory.info(logger, "================= > JPAHBsaeDefultIndexClient   isOpen  this not work ! defult true ;");
		return true;
	}

}
